﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace Mcmurphy.Common
{
    public class CssCombiner
    {
        /// <summary>
        /// 压缩并合并CSS文件内容
        /// </summary>
        /// <param name="cssPaths">文件路径列表</param>
        /// <param name="serverPath">站点物理路径</param>
        /// <param name="isCompress">是否压缩</param>
        /// <returns></returns>
        public static string CombineAndCompressCss(string[] cssPaths, string serverPath, bool isCompress)
        {
            var cssBuilder = new StringBuilder();
            foreach (var path in cssPaths)
            {
                if (File.Exists(path))
                {
                    var fileContent = AutoDetectEncodingFileReader.ReadFileContent(path, Encoding.Default);
                    if (isCompress)
                    {
                        fileContent = CompressCSS(fileContent);
                    }
                    cssBuilder.Append(fileContent);
                }
                else
                {
                    cssBuilder.Append(string.Format("/*未找到文件{0}*/", path.Replace(serverPath, "")));
                }
            }
            return cssBuilder.ToString();
        }

        /// <summary>
        /// 压缩css内容，去掉注释空格等
        /// 网上找的方法
        /// </summary>
        /// <param name="originCSS"></param>
        /// <returns></returns>
        public static string CompressCSS(string originCSS)
        {
            if (originCSS.Length == 0)
            {
                return originCSS;
            }
            StringBuilder finalCSS = new StringBuilder(originCSS.Length);

            //去注释
            char preChar = originCSS[0];
            bool isCurrentInComment = false;
            foreach (char currentChar in originCSS)
            {
                if (preChar == '/' && currentChar == '*')
                {
                    finalCSS.Remove(finalCSS.Length - 1, 1);
                    isCurrentInComment = true;
                    preChar = currentChar;
                    continue;
                }
                if (preChar == '*' && currentChar == '/')
                {
                    isCurrentInComment = false;
                    preChar = currentChar;
                    continue;
                }
                if (isCurrentInComment)
                {
                    preChar = currentChar;
                    continue;
                }

                finalCSS.Append(currentChar);
                preChar = currentChar;
            }

            originCSS = finalCSS.ToString();
            finalCSS.Clear();

            //去除属性前的空格和制表符
            bool isCurrentInNewProperty = false;
            foreach (char currentChar in originCSS)
            {
                if (currentChar == '{' || currentChar == ';')
                {
                    isCurrentInNewProperty = true;
                    finalCSS.Append(currentChar);
                    continue;
                }
                if (isCurrentInNewProperty)
                {
                    if (currentChar != ' ' && currentChar != '\t' && currentChar != '\r' && currentChar != '\n')
                    {
                        isCurrentInNewProperty = false;
                        finalCSS.Append(currentChar);
                        continue;
                    }
                    continue;
                }
                finalCSS.Append(currentChar);
            }

            originCSS = finalCSS.ToString();
            finalCSS.Clear();

            //去样式前空格和制表符，例如：}   Body{
            bool isCurrentInNewStyleNameStart = false;
            foreach (char currentChar in originCSS)
            {
                if (currentChar == '}')
                {
                    isCurrentInNewStyleNameStart = true;
                    finalCSS.Append(currentChar);
                    continue;
                }
                if (isCurrentInNewStyleNameStart)
                {
                    if (currentChar != ' ' && currentChar != '\t' && currentChar != '\r' && currentChar != '\n')
                    {
                        isCurrentInNewStyleNameStart = false;
                        finalCSS.Append(currentChar);
                        continue;
                    }
                    continue;
                }
                finalCSS.Append(currentChar);
            }
            //反转序列以去除样式名后的空格，例如：body img        {
            char[] finalCSSArray = finalCSS.ToString().ToCharArray();
            Array.Reverse(finalCSSArray);
            originCSS = new string(finalCSSArray);
            finalCSS.Clear();
            bool isCurrentInNewStyleNameEnd = false;
            foreach (char currentChar in originCSS)
            {
                if (currentChar == '{')
                {
                    isCurrentInNewStyleNameEnd = true;
                    finalCSS.Append(currentChar);
                    continue;
                }
                if (isCurrentInNewStyleNameEnd)
                {
                    if (currentChar != ' ' && currentChar != '\t' && currentChar != '\r' && currentChar != '\n')
                    {
                        isCurrentInNewStyleNameEnd = false;
                        finalCSS.Append(currentChar);
                        continue;
                    }
                    continue;
                }
                finalCSS.Append(currentChar);
            }
            //反转回正常序列
            finalCSSArray = finalCSS.ToString().ToCharArray();
            Array.Reverse(finalCSSArray);
            originCSS = new string(finalCSSArray);
            finalCSS.Clear();

            ////去换行
            foreach (char currentChar in originCSS)
            {
                if (currentChar == '\r' || currentChar == '\n')
                {
                    continue;
                }
                finalCSS.Append(currentChar);
            }

            return finalCSS.ToString();
        }
    }
}
